#ifndef __TRANSACTION_H__
#define __TRANSACTION_H__

#include <stdint.h>
#include "iota/conversion.h"
#include "iota/iota_types.h"


typedef struct TX {
	char m_signatureMessageFragment[2187];
	char m_address[81];
	char m_value[27];
	char m_obsoleteTag[27];
	char m_timestamp[9];
	char m_currentIndex[9];
	char m_lastIndex[9];
	char m_bundle[81];
	char m_trunkTransaction[81];
	char m_branchTransaction[81];
	char m_tag[27];
	char m_attachmentTimestamp[9];
	char m_attachmentTimestampLower[9];
	char m_attachmentTimestampUpper[9];
	char m_nonce[27];
	char m_zeroterminator;
} TX_t;

class Transaction {
public:
	enum Type { Empty, Input, Output, Remainder, Signature };
	TX_t* m_charTX;
private:
	//Conversion*	m_conv;
	Type m_type;
	Transaction* m_next;
	Transaction* m_prev;

	uint32_t m_addressIndex;
	int64_t m_value;
	uint32_t m_timestamp;
	uint32_t m_currentIndex;
	uint32_t m_lastIndex;
	uint32_t m_attachmentTimestamp;
	uint32_t m_attachmentTimestampLowerBound;
	uint32_t m_attachmentTimestampUpperBound;

	uint8_t	 m_bundleBytes[96];

protected:
	char* int64_to_chars(int64_t value, char *chars, unsigned int num_trytes);
	void get_address(const unsigned char *seed_bytes, uint32_t idx, unsigned int security, char *address);
	char* char_copy(char *destination, const char *source, unsigned int len);
//	void set_bundle_hash(const BUNDLE_CTX *bundle_ctx, TX_OBJECT *txs, unsigned int num_txs);

public:
	void convertIntValues();
	void increment_obsolete_tag(unsigned int tag_increment);
	Transaction();
	void setDataPointer(TX_t *p) { m_charTX = p ; }
	void init();

	void setTXPtr(TX_t* tx) { m_charTX = tx; }
	Type getType() { return m_type; }
	void setType(Type type) { m_type = type; }
	void setMessage(const char* msg);
	void setAddress(const char* addr);
	void setValue(int64_t value);
	void setObsoleteTag(char* tag);
	void setTimestamp(uint32_t timestamp);
	void setCurrentIndex(uint32_t index);
	void setLastIndex(uint32_t index);
	void setBundle(const char* bundle);
	void setTrunkTransaction(const char* trunk);
	void setBranchTransaction(const char* branch);
	void setTag(const char* tag);
	void setAttachmentTimestamp(int64_t timestamp);
	void setAttachmentTimestampLowerBound(int64_t timestamp);
	void setAttachmentTimestampUpperBound(int64_t timestamp);
	void setNonce(const char* nonce);
	void setAddressIndex(uint32_t idx);

	//void setTimestampChars(char* timestamp);
	//void setLastIndexChars(char* index);
	void setValueChars(const char* value);

	uint32_t getTimestamp() { return m_timestamp; }
	char* getTag() { return m_charTX->m_tag; }
	char* getAddress() { return m_charTX->m_address; }
	int64_t getValue() { return m_value; }
	uint32_t getAddressIndex() { return m_addressIndex; }
	int getCurrentIndex() { return m_currentIndex; }
	int getLastIndex() { return m_lastIndex; }
	char* getsignatureMessageFragment() { return m_charTX->m_signatureMessageFragment; }
	char* getRawPtr() { return (char*) &m_charTX->m_signatureMessageFragment[0]; }
	char* getTrunkTransaction() { return m_charTX->m_trunkTransaction; }
	char* getBranchTransaction() { return m_charTX->m_branchTransaction; }
	char* getBundle() { return m_charTX->m_bundle; }
	char* getObsoleteTag() { return m_charTX->m_obsoleteTag; }
	/*char* getTimestampChars() { return m_charTX.m_timestamp; }
	char* getLastIndexChars() { return m_charTX.m_lastIndex; }*/

	void getFullAddress(char* fullAddress);
	void parse(char* tx);

	void calcBundleBytes();

	uint8_t* getBundleBytes() { return m_bundleBytes; }

	void reverseLink() {
		Transaction* tmp = m_next;
		m_next = m_prev;
		m_prev = tmp;
	}

	void deleteLink() {
		m_next = 0;
		m_prev = 0;
	}

	void setNext(Transaction* next) {
		m_next = next;
	}
	void setPrev(Transaction* prev) {
		if (prev) {
			prev->setNext(this);
		}
		m_prev = prev;
	}
	Transaction* getNext() {
		return m_next;
	}
	Transaction* getPrev() {
		return m_prev;
	}
};

#endif
